﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Common;
using System.Reflection;

using Dude.Extensions;

namespace Dude.Data
{
    public static class Providers
    {
        private static Dictionary<string, DbProviderFactory> factorycache = new Dictionary<string, DbProviderFactory>();

        public static DbProviderFactory GetDbProviderFactory(string ProviderName)
        {
            string cacheid = string.Format("{0}@{1}", ProviderName, "");
            DbProviderFactory factory;
            if (factorycache.TryGetValue(cacheid, out factory))
            {
                return factory;
            }

            factory = System.Data.Common.DbProviderFactories.GetFactory(ProviderName);
            if (factory != null) factorycache.Add(cacheid, factory);
            return factory;
        }
        
        public static DbProviderFactory GetDbProviderFactory(string ProviderName, string AssemblyName)
        {
            if (AssemblyName == null) AssemblyName = "";

            DbProviderFactory factory = null;

            string cacheid = string.Format("{0}@{1}",ProviderName,AssemblyName);

            if (factorycache.TryGetValue(cacheid, out factory))
            {
                return factory;
            }
            
            if (AssemblyName.IsNullOrEmpty())
            {
                return GetDbProviderFactory(ProviderName);
            }

            Assembly npgsql = Assembly.Load(AssemblyName);
            if (npgsql == null) return null;
            Type type = npgsql.GetType(ProviderName, false, false);
            if (type == null)
            {
                // try load provider case insensitive
                type = npgsql.GetType(ProviderName, false, true); 
            }
            if (type == null) return null;

            FieldInfo field = type.GetField("Instance", BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
            if ((field == null) || !field.FieldType.IsSubclassOf(typeof(DbProviderFactory))) return null;

            object fobj = field.GetValue(null);
            if (fobj == null) return null;

            factory =(DbProviderFactory)fobj;
            factorycache.Add(cacheid,factory);
            
            return factory;
        }

        public static Dude.Data.Meta.DbMetadataGenerator GetMetadataGenerator(DbProviderFactory factory)
        {

            return null;
        }
    }
}
